// Rectangle.cc

/*
   Copyright 2006 Corey Tabaka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include <Rectangle.h>

#if !defined(MIN) && !defined(MAX)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif

namespace gui {

Rectangle::Rectangle(int x, int y, int width, int height) {
	this->x = x;
	this->y = y;
	this->width = width;
	this->height = height;
}

Rectangle::Rectangle(const Rectangle &r) {
	Rectangle(r.x, r.y, r.width, r.height);
}

Rectangle::Rectangle(void) {
	x = y = width = height = 0;
}

Rectangle &Rectangle::operator=(const Rectangle &r) {
	x = r.x;
	y = r.y;
	width = r.width;
	height = r.height;
	
	return *this;
}

Rectangle::~Rectangle(void) {
}

void Rectangle::getIntersection(Rectangle &dest, const Rectangle &r) const {
	int tx1 = this->x;
	int ty1 = this->y;
	int rx1 = r.x;
	int ry1 = r.y;
	long tx2 = tx1; tx2 += this->width;
	long ty2 = ty1; ty2 += this->height;
	long rx2 = rx1; rx2 += r.width;
	long ry2 = ry1; ry2 += r.height;
	if (tx1 < rx1) tx1 = rx1;
	if (ty1 < ry1) ty1 = ry1;
	if (tx2 > rx2) tx2 = rx2;
	if (ty2 > ry2) ty2 = ry2;
	tx2 -= tx1;
	ty2 -= ty1;
	// tx2,ty2 will never overflow (they will never be
	// larger than the smallest of the two source w,h)
	// they might underflow, though...
	if (tx2 < 0x80000000) tx2 = 0x80000000;
	if (ty2 < 0x80000000) ty2 = 0x80000000;
	
	dest.x = tx1;
	dest.y = ty2;
	dest.width = (int) tx2;
	dest.height = (int) ty2;
}

void Rectangle::getUnion(Rectangle &dest, const Rectangle &r) const {
	int x1 = MIN(x, r.x);
	int x2 = MAX(x + width, r.x + r.width);
	int y1 = MIN(y, r.y);
	int y2 = MAX(y + height, r.y + r.height);
	
	dest.x = x1;
	dest.y = y1;
	dest.width = x2 - x1;
	dest.height = y2 - y1;
}

bool Rectangle::intersects(const Rectangle &r) const {
	int tw = width;
	int th = height;
	int rw = r.width;
	int rh = r.height;
	if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {
		return false;
	}
	int tx = x;
	int ty = y;
	int rx = r.x;
	int ry = r.y;
	rw += rx;
	rh += ry;
	tw += tx;
	th += ty;
	//      overflow || intersect
	return ((rw < rx || rw > tx) &&
		(rh < ry || rh > ty) &&
		(tw < tx || tw > rx) &&
		(th < ty || th > ry));
}

} // namespace gui
